
//1、result = expr1 ?? expr2  -> 如果发现 expr1 为 null，就返回 expr2 的值，否则就返回 expr1 的值
//void main(){
//  var a = null;
//  var b = a ?? "aa";
//  print(b);
//}

//2、expr1 ??= expr2  -> 若 expr1 为 null，则把 expr2 的值赋值给 expr1
//void main(){
//  var a = "value";
//  var b = null;
//  b ??= a;
//  print(b);
//}

//3、result = expr1?.value  -> 如果 expr1 不为 null 就返回 expr1.value，否则就会返回 null
//void main(){
//  //待测试
//}

//4、级联操作符（..） -> 可以让你对一个对象中字段进行链式调用操作

//5、运算符重载 -》 使用operator关键字定义重载函数
//class Vip {
//  final int level;
//  final int score;
//
//  const Vip(this.level, this.score);
//
//  bool operator >(Vip other) =>
//      level > other.level || (level == other.level && score > other.score);
//
//  bool operator <(Vip other) =>
//      level < other.level || (level == other.level && score < other.score);
//
//
//  @override
//  bool operator ==(covariant Vip other) =>
//      (level == other.level && score == other.score);
//
//  @override
//  int get hashCode => super.hashCode; //伴随着你还需要重写 hashCode，至于什么原因大家应该都知道
//}
//
//main() {
//  var userVip1 = Vip(4, 3500);
//  var userVip2 = Vip(4, 1200);
//  if(userVip1 > userVip2) {
//    print('userVip1 is super vip');
//  } else if(userVip1 < userVip2) {
//    print('userVip2 is super vip');
//  }
//}

//6、异常
//Dart 中的异常捕获方法和 Java、Kotlin 类似，使用的也是 try-catch-finally
//对特定异常的捕获使用 on 关键字
//Dart 中的常见异常有：NoSuchMethodError（当在一个对象上调用一个该对象没有 实现的函数会抛出该错误）、ArgumentError（调用函数的参数不合法会抛出这个错误）
//main() {
//  int num = 18;
//  int result = 0;
//  try {
//    result = num ~/ 0;
//  } catch (e) {//捕获到 IntegerDivisionByZeroException
//    print(e.toString());
//  } finally {
//    print('$result');
//  }
//}

//使用 on 关键字捕获特定的异常
//main() {
//  int num = 18;
//  int result = 0;
//  try {
//    result = num ~/ 0;
//  } on IntegerDivisionByZeroException catch (e) {//捕获特定异常
//    print(e.toString());
//  } finally {
//    print('$result');
//  }
//}

//7、函数的基本用法
//main() {
//  print('sum is ${sum(2, 5)}');
//}
//
//num sum(num a, num b) {
//  return a + b;
//}

//8、函数参数列表传参规则
//num a, num b, num c, num d 最普通的传参：调用时，参数个数和参数顺序必须固定
//add1(num a, num b, num c, num d) {
//  print(a + b + c + d);
//}
//
////[num a, num b, num c, num d]传参：调用时，参数个数不固定，但是参数顺序需要一一对应，不支持命名参数
//add2([num a, num b, num c, num d]) {
//  print(a + b + c + d);
//}
//
////{num a, num b, num c, num d}传参：调用时，参数个数不固定，参数顺序也可以不固定，支持命名参数，也叫可选参数，是 Dart 中的一大特性，这就是为啥 Flutter 代码那么多可选属性，大量使用可选参数
//add3({num a, num b, num c, num d}) {
//  print(a + b + c + d);
//}
//
////num a, num b, {num c, num d}传参：调用时，a、b 参数个数固定顺序固定，c、d 参数个数和顺序也可以不固定
//add4(num a, num b, {num c, num d}) {
//  print(a + b + c + d);
//}
//
//main() {
//  add1(100, 100, 100, 100); //最普通的传参：调用时，参数个数和参数顺序必须固定
//  add2(100, 100); //调用时，参数个数不固定，但是参数顺序需要一一对应，不支持命名参数（也就意味着顺序不变）
//  add3(
//      b: 200,
//      a: 200,
//      c: 100,
//      d: 100); //调用时，参数个数不固定，参数顺序也可以不固定，支持命名参数（也就意味着顺序可变）
//  add4(100, 100, d: 100, c: 100); //调用时，a、b 参数个数固定顺序笃定，c、d 参数个数和顺序也可以不固定
//}

//9、函数默认参数和可选参数
//add3({num a, num b, num c, num d = 100}) {//d 就是默认值参数，给的默认值是 100
//  print(a + b + c + d);
//}
//
//main() {
//  add3(b: 200, a: 100, c: 800);
//}

//10、函数类型与高阶函数
//main() {
//  Function square = (a) {
//    return a * a;
//  };
//
//  Function square2 = (a) {
//    return a * a * a;
//  };
//
//  print(add(3, 4, square, square2));
//}
//
//num add(num a, num b, [Function op, Function op2]) {
//  //函数作为参数传递
//  return op(a) + op2(b);
//}

//11、函数的简化以及箭头函数
//add4(num a, num b, {num c, num d}) {
//  print(a + b + c + d);
//  return a + b + c + d;
//}
//
//void main(){
//  print(add4(1, 2,c:3,d:4));
//}

//12、类的基本定义和使用
//abstract class Person {
//  String name;
//  int age;
//  double height;
//  Person(this.name, this.age, this.height);//注意，这里写法可能大家没见过， 这点和 Java 是不一样，这里实际上是一个 Dart 的语法糖。但是这里不如 Kotlin，Kotlin 是直接把 this.name 传值的过程都省了。
//}
//
//class Student extends Person {//和 Java 一样同时使用 extends 关键字表示继承
//  Student(String name, int age, double height, double grade): super(name, age, height);//在 Dart 里：类名(变量,变量,...) 是构造函数的写法，:super() 表示该构造调用父类，这里构造时传入三个参数
//}

//13、类中属性的 getter 和 setter 访问器（类似 Kotlin）
abstract class Person {
  String _name; ////相当于 kotlin 中的 var 修饰的变量有 setter、getter 访问器，在 Dart 中没有访问权限, 默认_下划线开头变量表示私有权限，外部文件无法访问
  final int _age;//相当于 kotlin 中的 val 修饰的变量只有 getter 访问器
  Person(this._name, this._age); //这是上述简写形式

  //使用 set 关键字 计算属性 自定义 setter 访问器
  set name(String name) => _name = name;
  //使用 get 关键字 计算属性 自定义 getter 访问器
  bool get isStudent => _age > 18;
}